<!DOCTYPE html>
<html lang="cn-ZH">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>class8 - Next.js SSR项目 | 摸鱼老萌新</title>
    <meta name="description" content="Front end project and tips sharing">
    <link rel="stylesheet" href="/assets/style.8f1fef60.css">
    <link rel="modulepreload" href="/assets/app.75d9ecf2.js">
    <link rel="modulepreload" href="/assets/articles_basic-bitdance_class08-next.js.md.893eef63.lean.js">
    
    <script id="check-dark-light">(()=>{const e=localStorage.getItem("vitepress-theme-appearance"),a=window.matchMedia("(prefers-color-scheme: dark)").matches;(!e||e==="auto"?a:e==="dark")&&document.documentElement.classList.add("dark")})();</script>
  </head>
  <body>
    <div id="app"><div class="Layout" data-v-c6a644e1><!--[--><!--]--><!--[--><span tabindex="-1" data-v-151f2593></span><a href="#VPContent" class="VPSkipLink visually-hidden" data-v-151f2593> Skip to content </a><!--]--><!----><header class="VPNav" data-v-c6a644e1 data-v-a71a30f1><div class="VPNavBar has-sidebar" data-v-a71a30f1 data-v-6f1d18b5><div class="container" data-v-6f1d18b5><div class="VPNavBarTitle has-sidebar" data-v-6f1d18b5 data-v-d5925166><a class="title" href="/" data-v-d5925166><!--[--><!--]--><!--[--><img class="VPImage logo" src="/logo.jpg" data-v-e13a1912><!--]--><!--[-->摸鱼老萌新<!--]--><!--[--><!--]--></a></div><div class="content" data-v-6f1d18b5><!--[--><!--]--><!----><nav aria-labelledby="main-nav-aria-label" class="VPNavBarMenu menu" data-v-6f1d18b5 data-v-f83db6ba><span id="main-nav-aria-label" class="visually-hidden" data-v-f83db6ba>Main Navigation</span><!--[--><!--[--><div class="VPFlyout VPNavBarMenuGroup" data-v-f83db6ba data-v-6ffb57d3><button type="button" class="button" aria-haspopup="true" aria-expanded="false" data-v-6ffb57d3><span class="text" data-v-6ffb57d3><!----> 前端 <svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="text-icon" data-v-6ffb57d3><path d="M12,16c-0.3,0-0.5-0.1-0.7-0.3l-6-6c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l5.3,5.3l5.3-5.3c0.4-0.4,1-0.4,1.4,0s0.4,1,0,1.4l-6,6C12.5,15.9,12.3,16,12,16z"></path></svg></span></button><div class="menu" data-v-6ffb57d3><div class="VPMenu" data-v-6ffb57d3 data-v-1c5d0cfc><div class="items" data-v-1c5d0cfc><!--[--><!--[--><div class="VPMenuLink" data-v-1c5d0cfc data-v-e8e0fb1d><a class="VPLink link" href="/articles/basic/index.html" data-v-e8e0fb1d data-v-3c355974><!--[-->基础<!--]--><!----></a></div><!--]--><!--[--><div class="VPMenuLink" data-v-1c5d0cfc data-v-e8e0fb1d><a class="VPLink link" href="/articles/vue/index.html" data-v-e8e0fb1d data-v-3c355974><!--[-->Vue<!--]--><!----></a></div><!--]--><!--[--><div class="VPMenuLink" data-v-1c5d0cfc data-v-e8e0fb1d><a class="VPLink link" href="/articles/react/index.html" data-v-e8e0fb1d data-v-3c355974><!--[-->React<!--]--><!----></a></div><!--]--><!--[--><div class="VPMenuLink" data-v-1c5d0cfc data-v-e8e0fb1d><a class="VPLink link" href="/articles/mini/index.html" data-v-e8e0fb1d data-v-3c355974><!--[-->小程序<!--]--><!----></a></div><!--]--><!--[--><div class="VPMenuLink" data-v-1c5d0cfc data-v-e8e0fb1d><a class="VPLink link" href="/articles/electron/index.html" data-v-e8e0fb1d data-v-3c355974><!--[-->Electron<!--]--><!----></a></div><!--]--><!--[--><div class="VPMenuLink" data-v-1c5d0cfc data-v-e8e0fb1d><a class="VPLink link" href="/articles/web3d/index.html" data-v-e8e0fb1d data-v-3c355974><!--[-->Web3D<!--]--><!----></a></div><!--]--><!--[--><div class="VPMenuLink" data-v-1c5d0cfc data-v-e8e0fb1d><a class="VPLink link" href="/articles/rust/01.%E5%9F%BA%E7%A1%80%E5%85%A5%E9%97%A8.html" data-v-e8e0fb1d data-v-3c355974><!--[-->Rust<!--]--><!----></a></div><!--]--><!--[--><div class="VPMenuLink" data-v-1c5d0cfc data-v-e8e0fb1d><a class="VPLink link" href="/articles/other/vitepress/01.vitepress%E7%9A%84%E6%90%AD%E5%BB%BA.html" data-v-e8e0fb1d data-v-3c355974><!--[-->其他<!--]--><!----></a></div><!--]--><!--]--></div><!--[--><!--]--></div></div></div><!--]--><!--[--><a class="VPLink link VPNavBarMenuLink" href="/leetcode/LEET_CODE%E9%A2%98%E8%A7%A3/47.%20%E5%85%A8%E6%8E%92%E5%88%97%20II.html" data-v-f83db6ba data-v-47a2263e data-v-3c355974><!--[-->算法<!--]--><!----></a><!--]--><!--[--><a class="VPLink link VPNavBarMenuLink" href="/intent/" data-v-f83db6ba data-v-47a2263e data-v-3c355974><!--[-->项目<!--]--><!----></a><!--]--><!--]--></nav><!----><div class="VPNavBarAppearance appearance" data-v-6f1d18b5 data-v-a3e7452b><button class="VPSwitch VPSwitchAppearance" type="button" role="switch" aria-label="toggle dark mode" aria-checked="false" data-v-a3e7452b data-v-1899cd41 data-v-086e8519><span class="check" data-v-086e8519><span class="icon" data-v-086e8519><!--[--><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="sun" data-v-1899cd41><path d="M12,18c-3.3,0-6-2.7-6-6s2.7-6,6-6s6,2.7,6,6S15.3,18,12,18zM12,8c-2.2,0-4,1.8-4,4c0,2.2,1.8,4,4,4c2.2,0,4-1.8,4-4C16,9.8,14.2,8,12,8z"></path><path d="M12,4c-0.6,0-1-0.4-1-1V1c0-0.6,0.4-1,1-1s1,0.4,1,1v2C13,3.6,12.6,4,12,4z"></path><path d="M12,24c-0.6,0-1-0.4-1-1v-2c0-0.6,0.4-1,1-1s1,0.4,1,1v2C13,23.6,12.6,24,12,24z"></path><path d="M5.6,6.6c-0.3,0-0.5-0.1-0.7-0.3L3.5,4.9c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l1.4,1.4c0.4,0.4,0.4,1,0,1.4C6.2,6.5,5.9,6.6,5.6,6.6z"></path><path d="M19.8,20.8c-0.3,0-0.5-0.1-0.7-0.3l-1.4-1.4c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l1.4,1.4c0.4,0.4,0.4,1,0,1.4C20.3,20.7,20,20.8,19.8,20.8z"></path><path d="M3,13H1c-0.6,0-1-0.4-1-1s0.4-1,1-1h2c0.6,0,1,0.4,1,1S3.6,13,3,13z"></path><path d="M23,13h-2c-0.6,0-1-0.4-1-1s0.4-1,1-1h2c0.6,0,1,0.4,1,1S23.6,13,23,13z"></path><path d="M4.2,20.8c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l1.4-1.4c0.4-0.4,1-0.4,1.4,0s0.4,1,0,1.4l-1.4,1.4C4.7,20.7,4.5,20.8,4.2,20.8z"></path><path d="M18.4,6.6c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l1.4-1.4c0.4-0.4,1-0.4,1.4,0s0.4,1,0,1.4l-1.4,1.4C18.9,6.5,18.6,6.6,18.4,6.6z"></path></svg><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="moon" data-v-1899cd41><path d="M12.1,22c-0.3,0-0.6,0-0.9,0c-5.5-0.5-9.5-5.4-9-10.9c0.4-4.8,4.2-8.6,9-9c0.4,0,0.8,0.2,1,0.5c0.2,0.3,0.2,0.8-0.1,1.1c-2,2.7-1.4,6.4,1.3,8.4c2.1,1.6,5,1.6,7.1,0c0.3-0.2,0.7-0.3,1.1-0.1c0.3,0.2,0.5,0.6,0.5,1c-0.2,2.7-1.5,5.1-3.6,6.8C16.6,21.2,14.4,22,12.1,22zM9.3,4.4c-2.9,1-5,3.6-5.2,6.8c-0.4,4.4,2.8,8.3,7.2,8.7c2.1,0.2,4.2-0.4,5.8-1.8c1.1-0.9,1.9-2.1,2.4-3.4c-2.5,0.9-5.3,0.5-7.5-1.1C9.2,11.4,8.1,7.7,9.3,4.4z"></path></svg><!--]--></span></span></button></div><div class="VPSocialLinks VPNavBarSocialLinks social-links" data-v-6f1d18b5 data-v-738bef5a data-v-f6988cfb><!--[--><a class="VPSocialLink" href="https://github.com/aiai0603" target="_blank" rel="noopener" data-v-f6988cfb data-v-e57698f6><svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>GitHub</title><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></a><!--]--></div><div class="VPFlyout VPNavBarExtra extra" data-v-6f1d18b5 data-v-e89b88d7 data-v-6ffb57d3><button type="button" class="button" aria-haspopup="true" aria-expanded="false" aria-label="extra navigation" data-v-6ffb57d3><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="icon" data-v-6ffb57d3><circle cx="12" cy="12" r="2"></circle><circle cx="19" cy="12" r="2"></circle><circle cx="5" cy="12" r="2"></circle></svg></button><div class="menu" data-v-6ffb57d3><div class="VPMenu" data-v-6ffb57d3 data-v-1c5d0cfc><!----><!--[--><!--[--><!----><div class="group" data-v-e89b88d7><div class="item appearance" data-v-e89b88d7><p class="label" data-v-e89b88d7>Appearance</p><div class="appearance-action" data-v-e89b88d7><button class="VPSwitch VPSwitchAppearance" type="button" role="switch" aria-label="toggle dark mode" aria-checked="false" data-v-e89b88d7 data-v-1899cd41 data-v-086e8519><span class="check" data-v-086e8519><span class="icon" data-v-086e8519><!--[--><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="sun" data-v-1899cd41><path d="M12,18c-3.3,0-6-2.7-6-6s2.7-6,6-6s6,2.7,6,6S15.3,18,12,18zM12,8c-2.2,0-4,1.8-4,4c0,2.2,1.8,4,4,4c2.2,0,4-1.8,4-4C16,9.8,14.2,8,12,8z"></path><path d="M12,4c-0.6,0-1-0.4-1-1V1c0-0.6,0.4-1,1-1s1,0.4,1,1v2C13,3.6,12.6,4,12,4z"></path><path d="M12,24c-0.6,0-1-0.4-1-1v-2c0-0.6,0.4-1,1-1s1,0.4,1,1v2C13,23.6,12.6,24,12,24z"></path><path d="M5.6,6.6c-0.3,0-0.5-0.1-0.7-0.3L3.5,4.9c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l1.4,1.4c0.4,0.4,0.4,1,0,1.4C6.2,6.5,5.9,6.6,5.6,6.6z"></path><path d="M19.8,20.8c-0.3,0-0.5-0.1-0.7-0.3l-1.4-1.4c-0.4-0.4-0.4-1,0-1.4s1-0.4,1.4,0l1.4,1.4c0.4,0.4,0.4,1,0,1.4C20.3,20.7,20,20.8,19.8,20.8z"></path><path d="M3,13H1c-0.6,0-1-0.4-1-1s0.4-1,1-1h2c0.6,0,1,0.4,1,1S3.6,13,3,13z"></path><path d="M23,13h-2c-0.6,0-1-0.4-1-1s0.4-1,1-1h2c0.6,0,1,0.4,1,1S23.6,13,23,13z"></path><path d="M4.2,20.8c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l1.4-1.4c0.4-0.4,1-0.4,1.4,0s0.4,1,0,1.4l-1.4,1.4C4.7,20.7,4.5,20.8,4.2,20.8z"></path><path d="M18.4,6.6c-0.3,0-0.5-0.1-0.7-0.3c-0.4-0.4-0.4-1,0-1.4l1.4-1.4c0.4-0.4,1-0.4,1.4,0s0.4,1,0,1.4l-1.4,1.4C18.9,6.5,18.6,6.6,18.4,6.6z"></path></svg><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="moon" data-v-1899cd41><path d="M12.1,22c-0.3,0-0.6,0-0.9,0c-5.5-0.5-9.5-5.4-9-10.9c0.4-4.8,4.2-8.6,9-9c0.4,0,0.8,0.2,1,0.5c0.2,0.3,0.2,0.8-0.1,1.1c-2,2.7-1.4,6.4,1.3,8.4c2.1,1.6,5,1.6,7.1,0c0.3-0.2,0.7-0.3,1.1-0.1c0.3,0.2,0.5,0.6,0.5,1c-0.2,2.7-1.5,5.1-3.6,6.8C16.6,21.2,14.4,22,12.1,22zM9.3,4.4c-2.9,1-5,3.6-5.2,6.8c-0.4,4.4,2.8,8.3,7.2,8.7c2.1,0.2,4.2-0.4,5.8-1.8c1.1-0.9,1.9-2.1,2.4-3.4c-2.5,0.9-5.3,0.5-7.5-1.1C9.2,11.4,8.1,7.7,9.3,4.4z"></path></svg><!--]--></span></span></button></div></div></div><div class="group" data-v-e89b88d7><div class="item social-links" data-v-e89b88d7><div class="VPSocialLinks social-links-list" data-v-e89b88d7 data-v-f6988cfb><!--[--><a class="VPSocialLink" href="https://github.com/aiai0603" target="_blank" rel="noopener" data-v-f6988cfb data-v-e57698f6><svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>GitHub</title><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></a><!--]--></div></div></div><!--]--><!--]--></div></div></div><!--[--><!--]--><button type="button" class="VPNavBarHamburger hamburger" aria-label="mobile navigation" aria-expanded="false" aria-controls="VPNavScreen" data-v-6f1d18b5 data-v-e5dd9c1c><span class="container" data-v-e5dd9c1c><span class="top" data-v-e5dd9c1c></span><span class="middle" data-v-e5dd9c1c></span><span class="bottom" data-v-e5dd9c1c></span></span></button></div></div></div><!----></header><div class="VPLocalNav" data-v-c6a644e1 data-v-aac27d5e><button class="menu" aria-expanded="false" aria-controls="VPSidebarNav" data-v-aac27d5e><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" viewbox="0 0 24 24" class="menu-icon" data-v-aac27d5e><path d="M17,11H3c-0.6,0-1-0.4-1-1s0.4-1,1-1h14c0.6,0,1,0.4,1,1S17.6,11,17,11z"></path><path d="M21,7H3C2.4,7,2,6.6,2,6s0.4-1,1-1h18c0.6,0,1,0.4,1,1S21.6,7,21,7z"></path><path d="M21,15H3c-0.6,0-1-0.4-1-1s0.4-1,1-1h18c0.6,0,1,0.4,1,1S21.6,15,21,15z"></path><path d="M17,19H3c-0.6,0-1-0.4-1-1s0.4-1,1-1h14c0.6,0,1,0.4,1,1S17.6,19,17,19z"></path></svg><span class="menu-text" data-v-aac27d5e>Menu</span></button><a class="top-link" href="#" data-v-aac27d5e> Return to top </a></div><aside class="VPSidebar" data-v-c6a644e1 data-v-f332cb62><nav class="nav" id="VPSidebarNav" aria-labelledby="sidebar-aria-label" tabindex="-1" data-v-f332cb62><span class="visually-hidden" id="sidebar-aria-label" data-v-f332cb62> Sidebar Navigation </span><!--[--><div class="group" data-v-f332cb62><section class="VPSidebarGroup collapsible collapsed" data-v-f332cb62 data-v-2976c796><div class="title" role="button" data-v-2976c796><h2 class="title-text" data-v-2976c796>前端基础</h2><div class="action" data-v-2976c796><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewbox="0 0 24 24" class="icon minus" data-v-2976c796><path d="M19,2H5C3.3,2,2,3.3,2,5v14c0,1.7,1.3,3,3,3h14c1.7,0,3-1.3,3-3V5C22,3.3,20.7,2,19,2zM20,19c0,0.6-0.4,1-1,1H5c-0.6,0-1-0.4-1-1V5c0-0.6,0.4-1,1-1h14c0.6,0,1,0.4,1,1V19z"></path><path d="M16,11H8c-0.6,0-1,0.4-1,1s0.4,1,1,1h8c0.6,0,1-0.4,1-1S16.6,11,16,11z"></path></svg><svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24" class="icon plus" data-v-2976c796><path d="M19,2H5C3.3,2,2,3.3,2,5v14c0,1.7,1.3,3,3,3h14c1.7,0,3-1.3,3-3V5C22,3.3,20.7,2,19,2z M20,19c0,0.6-0.4,1-1,1H5c-0.6,0-1-0.4-1-1V5c0-0.6,0.4-1,1-1h14c0.6,0,1,0.4,1,1V19z"></path><path d="M16,11h-3V8c0-0.6-0.4-1-1-1s-1,0.4-1,1v3H8c-0.6,0-1,0.4-1,1s0.4,1,1,1h3v3c0,0.6,0.4,1,1,1s1-0.4,1-1v-3h3c0.6,0,1-0.4,1-1S16.6,11,16,11z"></path></svg></div></div><div class="items" data-v-2976c796><!--[--><!--[--><a class="VPLink link link" href="/articles/basic/index.html" style="padding-left:0px;" data-v-2cfe069a data-v-3c355974><!--[--><span class="link-text" data-v-2cfe069a>index</span><!--]--><!----></a><!----><!--]--><!--]--></div></section></div><div class="group" data-v-f332cb62><section class="VPSidebarGroup collapsible" data-v-f332cb62 data-v-2976c796><div class="title" role="button" data-v-2976c796><h2 class="title-text" data-v-2976c796>字节青训笔记</h2><div class="action" data-v-2976c796><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewbox="0 0 24 24" class="icon minus" data-v-2976c796><path d="M19,2H5C3.3,2,2,3.3,2,5v14c0,1.7,1.3,3,3,3h14c1.7,0,3-1.3,3-3V5C22,3.3,20.7,2,19,2zM20,19c0,0.6-0.4,1-1,1H5c-0.6,0-1-0.4-1-1V5c0-0.6,0.4-1,1-1h14c0.6,0,1,0.4,1,1V19z"></path><path d="M16,11H8c-0.6,0-1,0.4-1,1s0.4,1,1,1h8c0.6,0,1-0.4,1-1S16.6,11,16,11z"></path></svg><svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24" class="icon plus" data-v-2976c796><path d="M19,2H5C3.3,2,2,3.3,2,5v14c0,1.7,1.3,3,3,3h14c1.7,0,3-1.3,3-3V5C22,3.3,20.7,2,19,2z M20,19c0,0.6-0.4,1-1,1H5c-0.6,0-1-0.4-1-1V5c0-0.6,0.4-1,1-1h14c0.6,0,1,0.4,1,1V19z"></path><path d="M16,11h-3V8c0-0.6-0.4-1-1-1s-1,0.4-1,1v3H8c-0.6,0-1,0.4-1,1s0.4,1,1,1h3v3c0,0.6,0.4,1,1,1s1-0.4,1-1v-3h3c0.6,0,1-0.4,1-1S16.6,11,16,11z"></path></svg></div></div><div class="items" data-v-2976c796><!--[--><!--[--><a class="VPLink link link" href="/articles/basic-bitdance/class01-html.html" style="padding-left:0px;" data-v-2cfe069a data-v-3c355974><!--[--><span class="link-text" data-v-2cfe069a>class01-html</span><!--]--><!----></a><!----><!--]--><!--[--><a class="VPLink link link" href="/articles/basic-bitdance/class02-css.html" style="padding-left:0px;" data-v-2cfe069a data-v-3c355974><!--[--><span class="link-text" data-v-2cfe069a>class02-css</span><!--]--><!----></a><!----><!--]--><!--[--><a class="VPLink link link" href="/articles/basic-bitdance/class03-js.html" style="padding-left:0px;" data-v-2cfe069a data-v-3c355974><!--[--><span class="link-text" data-v-2cfe069a>class03-js</span><!--]--><!----></a><!----><!--]--><!--[--><a class="VPLink link link" href="/articles/basic-bitdance/class04-typescript.html" style="padding-left:0px;" data-v-2cfe069a data-v-3c355974><!--[--><span class="link-text" data-v-2cfe069a>class04-typescript</span><!--]--><!----></a><!----><!--]--><!--[--><a class="VPLink link link" href="/articles/basic-bitdance/class05-http.html" style="padding-left:0px;" data-v-2cfe069a data-v-3c355974><!--[--><span class="link-text" data-v-2cfe069a>class05-http</span><!--]--><!----></a><!----><!--]--><!--[--><a class="VPLink link link" href="/articles/basic-bitdance/class06-react.html" style="padding-left:0px;" data-v-2cfe069a data-v-3c355974><!--[--><span class="link-text" data-v-2cfe069a>class06-react</span><!--]--><!----></a><!----><!--]--><!--[--><a class="VPLink link link" href="/articles/basic-bitdance/class07-node.html" style="padding-left:0px;" data-v-2cfe069a data-v-3c355974><!--[--><span class="link-text" data-v-2cfe069a>class07-node</span><!--]--><!----></a><!----><!--]--><!--[--><a class="VPLink link link active" href="/articles/basic-bitdance/class08-next.js.html" style="padding-left:0px;" data-v-2cfe069a data-v-3c355974><!--[--><span class="link-text" data-v-2cfe069a>class08-next.js</span><!--]--><!----></a><!----><!--]--><!--[--><a class="VPLink link link" href="/articles/basic-bitdance/class08.5-%E5%BC%80%E5%8F%91%E6%8A%80%E5%B7%A7.html" style="padding-left:0px;" data-v-2cfe069a data-v-3c355974><!--[--><span class="link-text" data-v-2cfe069a>class08.5-开发技巧</span><!--]--><!----></a><!----><!--]--><!--[--><a class="VPLink link link" href="/articles/basic-bitdance/class09-%E8%B7%A8%E7%AB%AF%E6%8A%80%E6%9C%AF.html" style="padding-left:0px;" data-v-2cfe069a data-v-3c355974><!--[--><span class="link-text" data-v-2cfe069a>class09-跨端技术</span><!--]--><!----></a><!----><!--]--><!--[--><a class="VPLink link link" href="/articles/basic-bitdance/class10-%E8%B0%83%E8%AF%95.html" style="padding-left:0px;" data-v-2cfe069a data-v-3c355974><!--[--><span class="link-text" data-v-2cfe069a>class10-调试</span><!--]--><!----></a><!----><!--]--><!--[--><a class="VPLink link link" href="/articles/basic-bitdance/class11-%E5%AE%89%E5%85%A8.html" style="padding-left:0px;" data-v-2cfe069a data-v-3c355974><!--[--><span class="link-text" data-v-2cfe069a>class11-安全</span><!--]--><!----></a><!----><!--]--><!--[--><a class="VPLink link link" href="/articles/basic-bitdance/class12-%E7%9B%91%E6%8E%A7sdk.html" style="padding-left:0px;" data-v-2cfe069a data-v-3c355974><!--[--><span class="link-text" data-v-2cfe069a>class12-监控sdk</span><!--]--><!----></a><!----><!--]--><!--[--><a class="VPLink link link" href="/articles/basic-bitdance/class13-webpack.html" style="padding-left:0px;" data-v-2cfe069a data-v-3c355974><!--[--><span class="link-text" data-v-2cfe069a>class13-webpack</span><!--]--><!----></a><!----><!--]--><!--[--><a class="VPLink link link" href="/articles/basic-bitdance/class14-vite.html" style="padding-left:0px;" data-v-2cfe069a data-v-3c355974><!--[--><span class="link-text" data-v-2cfe069a>class14-vite</span><!--]--><!----></a><!----><!--]--><!--[--><a class="VPLink link link" href="/articles/basic-bitdance/class15-%E5%8F%AF%E8%A7%86%E5%8C%96.html" style="padding-left:0px;" data-v-2cfe069a data-v-3c355974><!--[--><span class="link-text" data-v-2cfe069a>class15-可视化</span><!--]--><!----></a><!----><!--]--><!--]--></div></section></div><!--]--></nav></aside><div class="VPContent has-sidebar" id="VPContent" data-v-c6a644e1 data-v-c95df128><div class="VPDoc has-sidebar has-aside" data-v-c95df128 data-v-37ebe389><div class="container" data-v-37ebe389><div class="aside" data-v-37ebe389><div class="aside-curtain" data-v-37ebe389></div><div class="aside-container" data-v-37ebe389><div class="aside-content" data-v-37ebe389><div class="VPDocAside" data-v-37ebe389 data-v-afc4c1a1><!--[--><!--]--><!--[--><!--]--><div class="VPDocAsideOutline" data-v-afc4c1a1 data-v-2865c0b0><div class="content" data-v-2865c0b0><div class="outline-marker" data-v-2865c0b0></div><div class="outline-title" data-v-2865c0b0>On this page</div><nav aria-labelledby="doc-outline-aria-label" data-v-2865c0b0><span class="visually-hidden" id="doc-outline-aria-label" data-v-2865c0b0> Table of Contents for current page </span><ul class="root" data-v-2865c0b0 data-v-1188541a><!--[--><!--]--></ul></nav></div></div><!--[--><!--]--><div class="spacer" data-v-afc4c1a1></div><!--[--><!--]--><!----><!--[--><!--]--><!--[--><!--]--></div></div></div></div><div class="content" data-v-37ebe389><div class="content-container" data-v-37ebe389><!--[--><!--]--><main class="main" data-v-37ebe389><div style="position:relative;" class="vp-doc _articles_basic-bitdance_class08-next_js" data-v-37ebe389><div><h1 id="class8-next-js-ssr项目" tabindex="-1">class8 - Next.js SSR项目 <a class="header-anchor" href="#class8-next-js-ssr项目" aria-hidden="true">#</a></h1><p>这节课将讲述为什么要使用 ssr 渲染，以及如何使用 next.js 进行 ssr 项目的开发和部署</p><p>先给出 next.js 的官网，本教程只是进行简单的学习笔记的记录，更详细的开发需要你自行深入学习</p><p><a href="https://www.nextjs.cn/docs/getting-started" target="_blank" rel="noreferrer">https://www.nextjs.cn/docs/getting-started</a></p><h2 id="ssr-csr-ssg" tabindex="-1">SSR CSR SSG <a class="header-anchor" href="#ssr-csr-ssg" aria-hidden="true">#</a></h2><ul><li>CSR</li></ul><p>CSR 是指客户端渲染，它是流程是：用户输入地址，客户端向服务器发送请求，服务器将页面的相关代码原封不动的传递给浏览器，浏览器解析文件，请求ajax向服务器再次请求一些数据，浏览器拿到ajax请求返回的数据后，将数据渲染在页面上，客户端必须等到所有 Javascript 代码加载后才能呈现页面并向用户显示内容。</p><ul><li>SSG</li></ul><p>SSG 静态站点生成是指：当你创建一个站点时，我们需要预先提供应用程序的所有内容和数据。使用 SSG 意味着我们已经在构建步骤中生成了完整的 HTML 文件在，之后将页面放在 CDN 中，当用户打开你的站点后，直接返回给用户已经生成的页面。</p><ul><li>SSR</li></ul><p>SSR 服务端渲染是指：服务端第一次只把渲染好的 HTML 发给客户端，这样客户端就能直接显示出来网页的样式，首次绘制就很快，然后，客户端再根据 HTML 需要的 js 向服务端请求 js，然后客户端再把 js 装到已经绘制好的 HTML 上</p><h2 id="为什么要使用服务端渲染" tabindex="-1">为什么要使用服务端渲染 <a class="header-anchor" href="#为什么要使用服务端渲染" aria-hidden="true">#</a></h2><p>尽管像 React 这样的现代基于 Javascript 的前端框架帮助我们开发了强大的动态网站，但它们有一个主要缺点：客户端必须等到所有 Javascript 代码加载后才能呈现页面并向用户显示内容。由于页面的加载速度会显着影响其用户体验和搜索引擎排名，这已成为 Web 开发中的主要问题。Next.js 框架提供服务器端渲染，无需任何配置。服务器渲染的 HTML 页面将被发送到客户端，让他们立即看到页面的主要内容。之后事件处理程序等可以附加到生成好的 HTML 上，使其具有交互性。</p><h2 id="ssr的实现" tabindex="-1">SSR的实现 <a class="header-anchor" href="#ssr的实现" aria-hidden="true">#</a></h2><p>SSR 实现的关键就是：同构，一份代码，先通过服务端渲染(server-side rendering，ssr)，生成html字符串以及初始化数据，客户端拿到后，通过对html的dom进行patch和事件绑定对dom进行客户端激活(client-side hydration，csh)，这个整体的过程叫同构渲染。服务端将 HTML 片段提炼出来的过程就称为脱水，相应的，注水是在客户端要做的事，把只有样子的 HTML 恢复其功能。</p><h2 id="next-预渲染模式" tabindex="-1">Next 预渲染模式 <a class="header-anchor" href="#next-预渲染模式" aria-hidden="true">#</a></h2><p>Next.js 最突出的特性是预渲染，接收到 Javascript 代码后在客户端渲染网页是一个缓慢的过程。Next 通过向客户端发送每个页面的预渲染版本来解决这个问题。next有两种预渲染的方式：静态生成和服务端渲染，他们之间的区别就是什么时候生成html页面。</p><ul><li><p>静态生成，是在 build 应用的时候生成html, 然后每次请求的时候重用静态生成的页面</p><p>当我们可以在用户请求一个页面之前，就知道页面具体的样子，比如一篇博客，一份文档，我们就尽可能使用静态生成 ，这样你的所有 page（页面）都可以只构建一次并托管到 CDN 上，这比让服务器根据每个页面请求来渲染页面快得多。</p></li><li><p>服务端渲染，就是每次请求的时候都去生成html页面。</p><p>假设你的某个页面需要预渲染频繁更新的数据，比如一个实时监控界面，一份可以和用户交互的表单信息等等，你就需要使用服务端渲染，即SSR渲染</p></li></ul><p>在开发模式下（即npm run dev），每次请求的时候都会重新渲染页面，不管页面是不是静态生成的。</p><h2 id="初始化项目" tabindex="-1">初始化项目 <a class="header-anchor" href="#初始化项目" aria-hidden="true">#</a></h2><p>为了初始化一个项目，我们需要配置一个 package.json 文件初始化一个项目，然后下载依赖，你也可以直接使用官方初始化完成的 demo：</p><div class="language-shell"><button class="copy"></button><span class="lang">shell</span><pre><code><span class="line"><span style="color:#A6ACCD;">npx create-next-app nextjs-blog --use-npm --example </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">https://github.com/vercel/next-learn/tree/master/basics/learn-starter</span></span>
<span class="line"></span></code></pre></div><p>我们可以看到官方项目中有一个pages 文件夹，一个public 文件夹，一个styles 文件夹以及一些配置文件，如果是你自己创建的项目你需要自己创建一些项目，下面我们来讲每个文件夹的作用：</p><ul><li>public 文件夹</li></ul><p>这个文件夹存放了你需要引入的静态资源，比如图片 logo 等，等你在项目中使用这些资源时，你可以直接从 public 文件夹开始寻找这些资源，例如官方 demo 中的，vercel.svg 这个文件就在 public文件夹中</p><div class="language-html"><button class="copy"></button><span class="lang">html</span><pre><code><span class="line"><span style="color:#89DDFF;">&lt;</span><span style="color:#F07178;">img</span><span style="color:#89DDFF;"> </span><span style="color:#C792EA;">src</span><span style="color:#89DDFF;">=</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">/vercel.svg</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;"> </span><span style="color:#C792EA;">alt</span><span style="color:#89DDFF;">=</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">Vercel</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">/&gt;</span></span>
<span class="line"></span></code></pre></div><ul><li>pages 文件夹</li></ul><p>这个文件夹存放我们需要的页面，并且根据这个文件夹的逻辑配置我们的路由，而 index.js 文件可以作为某个路由的根进行配置，例如：pages/index.js 就需要你只需要直接访问 localhost:3000 就可以访问，而 pages/test/new.js 文件你需要使用 localhost:3000/test/new进行访问</p><ul><li>styles 文件夹</li></ul><p>存放我们需要的样式，这部分将在后续进行讲解</p><h2 id="配置页面" tabindex="-1">配置页面 <a class="header-anchor" href="#配置页面" aria-hidden="true">#</a></h2><p>在 Next.js 中，一个 page（页面） 就是一个从 .js、jsx、.ts 或 .tsx 文件导出（export）的 React 组件 ，这些文件存放在 pages 目录下。每个 page（页面）都使用其文件名作为路由（route），比如我们可以看到在官方的 demo 中，我们的 index.js 就导出了一个 react 组件：</p><div class="language-javascript"><button class="copy"></button><span class="lang">javascript</span><pre><code><span class="line"><span style="color:#89DDFF;">export</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">default</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">function</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">Home</span><span style="color:#89DDFF;">()</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;">return</span><span style="color:#F07178;"> (</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#89DDFF;">&lt;</span><span style="color:#F07178;">div</span><span style="color:#89DDFF;"> </span><span style="color:#C792EA;">className</span><span style="color:#89DDFF;">={</span><span style="color:#A6ACCD;">styles</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">container</span><span style="color:#89DDFF;">}&gt;</span></span>
<span class="line"><span style="color:#A6ACCD;">      </span><span style="color:#89DDFF;">&lt;</span><span style="color:#FFCB6B;">Head</span><span style="color:#89DDFF;">&gt;</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#89DDFF;">&lt;</span><span style="color:#F07178;">title</span><span style="color:#89DDFF;">&gt;</span><span style="color:#A6ACCD;">Create Next App</span><span style="color:#89DDFF;">&lt;/</span><span style="color:#F07178;">title</span><span style="color:#89DDFF;">&gt;</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#89DDFF;">&lt;</span><span style="color:#F07178;">link</span><span style="color:#89DDFF;"> </span><span style="color:#C792EA;">rel</span><span style="color:#89DDFF;">=</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">icon</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;"> </span><span style="color:#C792EA;">href</span><span style="color:#89DDFF;">=</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">/favicon.ico</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;"> /&gt;</span></span>
<span class="line"><span style="color:#A6ACCD;">      </span><span style="color:#89DDFF;">&lt;/</span><span style="color:#FFCB6B;">Head</span><span style="color:#89DDFF;">&gt;</span></span>
<span class="line"><span style="color:#A6ACCD;">      </span><span style="color:#89DDFF;">&lt;</span><span style="color:#F07178;">main</span><span style="color:#89DDFF;">&gt;</span></span>
<span class="line"><span style="color:#A6ACCD;">         //省略</span></span>
<span class="line"><span style="color:#A6ACCD;">      </span><span style="color:#89DDFF;">&lt;/</span><span style="color:#F07178;">main</span><span style="color:#89DDFF;">&gt;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#A6ACCD;">      </span><span style="color:#89DDFF;">&lt;</span><span style="color:#F07178;">style</span><span style="color:#89DDFF;"> </span><span style="color:#C792EA;">jsx</span><span style="color:#89DDFF;">&gt;{</span><span style="color:#89DDFF;">`</span></span>
<span class="line"><span style="color:#C3E88D;">      		//省略</span></span>
<span class="line"><span style="color:#C3E88D;">      </span><span style="color:#89DDFF;">`</span><span style="color:#89DDFF;">}&lt;/</span><span style="color:#F07178;">style</span><span style="color:#89DDFF;">&gt;</span></span>
<span class="line"><span style="color:#A6ACCD;">      </span><span style="color:#89DDFF;">&lt;</span><span style="color:#F07178;">style</span><span style="color:#89DDFF;"> </span><span style="color:#C792EA;">jsx</span><span style="color:#89DDFF;"> </span><span style="color:#C792EA;">global</span><span style="color:#89DDFF;">&gt;{</span><span style="color:#89DDFF;">`</span></span>
<span class="line"><span style="color:#C3E88D;">        	//省略</span></span>
<span class="line"><span style="color:#C3E88D;">      </span><span style="color:#89DDFF;">`</span><span style="color:#89DDFF;">}&lt;/</span><span style="color:#F07178;">style</span><span style="color:#89DDFF;">&gt;</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">&lt;/</span><span style="color:#F07178;">div</span><span style="color:#89DDFF;">&gt;</span></span>
<span class="line"><span style="color:#F07178;">  )</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span>
<span class="line"></span></code></pre></div><p>任何你想配置一个页面是头部内容，例如它的标题，你可以使用 next 提供的 head 组件来控制它：</p><div class="language-javascript"><button class="copy"></button><span class="lang">javascript</span><pre><code><span class="line"><span style="color:#89DDFF;">import</span><span style="color:#A6ACCD;"> Head </span><span style="color:#89DDFF;">from</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&#39;</span><span style="color:#C3E88D;">next/head</span><span style="color:#89DDFF;">&#39;</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#89DDFF;">export</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">default</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">function</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">Home</span><span style="color:#89DDFF;">()</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;">return</span><span style="color:#F07178;"> (</span></span>
<span class="line"><span style="color:#F07178;">      </span><span style="color:#89DDFF;">&lt;</span><span style="color:#FFCB6B;">Head</span><span style="color:#89DDFF;">&gt;</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#89DDFF;">&lt;</span><span style="color:#F07178;">title</span><span style="color:#89DDFF;">&gt;</span><span style="color:#A6ACCD;">Create Next App</span><span style="color:#89DDFF;">&lt;/</span><span style="color:#F07178;">title</span><span style="color:#89DDFF;">&gt;</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#89DDFF;">&lt;</span><span style="color:#F07178;">link</span><span style="color:#89DDFF;"> </span><span style="color:#C792EA;">rel</span><span style="color:#89DDFF;">=</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">icon</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;"> </span><span style="color:#C792EA;">href</span><span style="color:#89DDFF;">=</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">/favicon.ico</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;"> /&gt;</span></span>
<span class="line"><span style="color:#A6ACCD;">      </span><span style="color:#89DDFF;">&lt;/</span><span style="color:#FFCB6B;">Head</span><span style="color:#89DDFF;">&gt;</span></span>
<span class="line"><span style="color:#F07178;">  )</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span></code></pre></div><p>你可以在其他位置编写一个 react 组件然后再页面中使用他来降低一共页面的整体代码量以及良好的复用，比如我们创建 ccomponents / layout.js 文件编写一个组件：</p><div class="language-javascript"><button class="copy"></button><span class="lang">javascript</span><pre><code><span class="line"><span style="color:#89DDFF;">export</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">default</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">function</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">Layout</span><span style="color:#89DDFF;">({</span><span style="color:#A6ACCD;"> </span><span style="color:#A6ACCD;">children</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">})</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#89DDFF;">return</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">&lt;</span><span style="color:#F07178;">div</span><span style="color:#89DDFF;">&gt;</span><span style="color:#A6ACCD;">哈哈哈哈哈哈哈哈哈哈哈</span><span style="color:#89DDFF;">{</span><span style="color:#A6ACCD;">children</span><span style="color:#89DDFF;">}&lt;/</span><span style="color:#F07178;">div</span><span style="color:#89DDFF;">&gt;</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span></code></pre></div><p>然后我们可以在 index.js 里引入它：</p><div class="language-javascript"><button class="copy"></button><span class="lang">javascript</span><pre><code><span class="line"><span style="color:#89DDFF;">import</span><span style="color:#A6ACCD;"> Layout </span><span style="color:#89DDFF;">from</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&#39;</span><span style="color:#C3E88D;">../components/layout</span><span style="color:#89DDFF;">&#39;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#89DDFF;">export</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">default</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">function</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">Home</span><span style="color:#89DDFF;">()</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;">return</span><span style="color:#F07178;"> (</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#89DDFF;">&lt;</span><span style="color:#FFCB6B;">Layout</span><span style="color:#89DDFF;">&gt;</span></span>
<span class="line"><span style="color:#A6ACCD;">      </span><span style="color:#89DDFF;">&lt;</span><span style="color:#FFCB6B;">Head</span><span style="color:#89DDFF;">&gt;</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#89DDFF;">&lt;</span><span style="color:#F07178;">title</span><span style="color:#89DDFF;">&gt;</span><span style="color:#A6ACCD;">Create Next App</span><span style="color:#89DDFF;">&lt;/</span><span style="color:#F07178;">title</span><span style="color:#89DDFF;">&gt;</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#89DDFF;">&lt;</span><span style="color:#F07178;">link</span><span style="color:#89DDFF;"> </span><span style="color:#C792EA;">rel</span><span style="color:#89DDFF;">=</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">icon</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;"> </span><span style="color:#C792EA;">href</span><span style="color:#89DDFF;">=</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">/favicon.ico</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;"> /&gt;</span></span>
<span class="line"><span style="color:#A6ACCD;">      </span><span style="color:#89DDFF;">&lt;/</span><span style="color:#FFCB6B;">Head</span><span style="color:#89DDFF;">&gt;</span></span>
<span class="line"><span style="color:#A6ACCD;">     //省略</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">&lt;/</span><span style="color:#FFCB6B;">Layout</span><span style="color:#89DDFF;">&gt;</span></span>
<span class="line"><span style="color:#F07178;">  )</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span></code></pre></div><h2 id="配置样式" tabindex="-1">配置样式 <a class="header-anchor" href="#配置样式" aria-hidden="true">#</a></h2><p>我们可以用多种方式来配置我们组件的样式，首先我们要知道的是， next.js 13 内置了css 和 scss 的模块，我们可以直接编写，不需要任何插件和依赖的下载，根据官方的例子，我们可以使用 style in jsx 的方式添加样式，也就是用如下的内容包裹样式文件：</p><div class="language-jsx"><button class="copy"></button><span class="lang">jsx</span><pre><code><span class="line"><span style="color:#89DDFF;">&lt;</span><span style="color:#F07178;">style</span><span style="color:#89DDFF;"> </span><span style="color:#C792EA;">jsx</span><span style="color:#89DDFF;">&gt;{</span><span style="color:#89DDFF;">`</span></span>
<span class="line"><span style="color:#C3E88D;">   main {</span></span>
<span class="line"><span style="color:#C3E88D;">          padding: 5rem 0;</span></span>
<span class="line"><span style="color:#C3E88D;">        }</span></span>
<span class="line"><span style="color:#89DDFF;">`</span><span style="color:#89DDFF;">}&lt;/</span><span style="color:#F07178;">style</span><span style="color:#89DDFF;">&gt;</span></span>
<span class="line"></span></code></pre></div><p>我们也可以选择使用 css.modules 来添加样式，用这种方法添加的样式在编译的时候会加上一个哈希后缀，这种方法可以有效避免类名重复的问题：</p><div class="language-css"><button class="copy"></button><span class="lang">css</span><pre><code><span class="line"><span style="color:#89DDFF;">.</span><span style="color:#FFCB6B;">container</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">  </span><span style="color:#B2CCD6;">max-width</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">36rem</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#A6ACCD;">  </span><span style="color:#B2CCD6;">padding</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">0</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">1rem</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#A6ACCD;">  </span><span style="color:#B2CCD6;">margin</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#F78C6C;">3rem</span><span style="color:#A6ACCD;"> auto </span><span style="color:#F78C6C;">6rem</span><span style="color:#89DDFF;">;</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span></code></pre></div><p>引入</p><div class="language-javascript"><button class="copy"></button><span class="lang">javascript</span><pre><code><span class="line"><span style="color:#89DDFF;">import</span><span style="color:#A6ACCD;"> styles </span><span style="color:#89DDFF;">from</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&#39;</span><span style="color:#C3E88D;">./layout.module.css</span><span style="color:#89DDFF;">&#39;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#89DDFF;">export</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">default</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">function</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">Layout</span><span style="color:#89DDFF;">({</span><span style="color:#A6ACCD;"> </span><span style="color:#A6ACCD;">children</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">})</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;">return</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">&lt;</span><span style="color:#F07178;">div</span><span style="color:#89DDFF;"> </span><span style="color:#C792EA;">className</span><span style="color:#89DDFF;">={</span><span style="color:#A6ACCD;">styles</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">container</span><span style="color:#89DDFF;">}&gt;{</span><span style="color:#A6ACCD;">children</span><span style="color:#89DDFF;">}&lt;/</span><span style="color:#F07178;">div</span><span style="color:#89DDFF;">&gt;</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span></code></pre></div><p>你可以使用 cn 模块动态配置你的类名是否生效，就想这样：</p><div class="language-javascript"><button class="copy"></button><span class="lang">javascript</span><pre><code><span class="line"><span style="color:#89DDFF;">import</span><span style="color:#A6ACCD;"> styles </span><span style="color:#89DDFF;">from</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&#39;</span><span style="color:#C3E88D;">./alert.module.css</span><span style="color:#89DDFF;">&#39;</span></span>
<span class="line"><span style="color:#89DDFF;">import</span><span style="color:#A6ACCD;"> cn </span><span style="color:#89DDFF;">from</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&#39;</span><span style="color:#C3E88D;">classnames</span><span style="color:#89DDFF;">&#39;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#89DDFF;">export</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">default</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">function</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">Alert</span><span style="color:#89DDFF;">({</span><span style="color:#A6ACCD;"> </span><span style="color:#A6ACCD;">children</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#A6ACCD;">type</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">})</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;">return</span><span style="color:#F07178;"> (</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#89DDFF;">&lt;</span><span style="color:#F07178;">div</span></span>
<span class="line"><span style="color:#89DDFF;">      </span><span style="color:#C792EA;">className</span><span style="color:#89DDFF;">={</span><span style="color:#82AAFF;">cn</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#F07178;">[</span><span style="color:#A6ACCD;">styles</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">success</span><span style="color:#F07178;">]</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> type </span><span style="color:#89DDFF;">===</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&#39;</span><span style="color:#C3E88D;">success</span><span style="color:#89DDFF;">&#39;</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#F07178;">[</span><span style="color:#A6ACCD;">styles</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">error</span><span style="color:#F07178;">]</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> type </span><span style="color:#89DDFF;">===</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&#39;</span><span style="color:#C3E88D;">error</span><span style="color:#89DDFF;">&#39;</span></span>
<span class="line"><span style="color:#A6ACCD;">      </span><span style="color:#89DDFF;">}</span><span style="color:#A6ACCD;">)</span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#89DDFF;">    &gt;</span></span>
<span class="line"><span style="color:#A6ACCD;">      </span><span style="color:#89DDFF;">{</span><span style="color:#A6ACCD;">children</span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">&lt;/</span><span style="color:#F07178;">div</span><span style="color:#89DDFF;">&gt;</span></span>
<span class="line"><span style="color:#F07178;">  )</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span></code></pre></div><p>如果你想要一套样式在所有页面生效，你需要配置全局样式，你有两者方法进行配置，你可以在 pages 文件夹下方创建一个 _app.js 文件，如下引入你写好的样式：</p><div class="language-javascript"><button class="copy"></button><span class="lang">javascript</span><pre><code><span class="line"><span style="color:#89DDFF;">import</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&#39;</span><span style="color:#C3E88D;">../styles/global.css</span><span style="color:#89DDFF;">&#39;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#89DDFF;">export</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">default</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">function</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">App</span><span style="color:#89DDFF;">({</span><span style="color:#A6ACCD;"> </span><span style="color:#A6ACCD;">Component</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#A6ACCD;">pageProps</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">})</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;">return</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">&lt;</span><span style="color:#FFCB6B;">Component</span><span style="color:#89DDFF;"> {...</span><span style="color:#A6ACCD;">pageProps</span><span style="color:#89DDFF;">} /&gt;</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span></code></pre></div><p>你也可以选择使用全局的 style jsx 来进行全局样式的编写，就想例子里一样：</p><div class="language-javascript"><button class="copy"></button><span class="lang">javascript</span><pre><code><span class="line"><span style="color:#89DDFF;">&lt;</span><span style="color:#F07178;">style</span><span style="color:#89DDFF;"> </span><span style="color:#C792EA;">jsx</span><span style="color:#89DDFF;"> </span><span style="color:#C792EA;">global</span><span style="color:#89DDFF;">&gt;{</span><span style="color:#89DDFF;">`</span></span>
<span class="line"><span style="color:#C3E88D;">        html,</span></span>
<span class="line"><span style="color:#C3E88D;">        body {</span></span>
<span class="line"><span style="color:#C3E88D;">          padding: 0;</span></span>
<span class="line"><span style="color:#C3E88D;">          margin: 0;</span></span>
<span class="line"><span style="color:#C3E88D;">          font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto,</span></span>
<span class="line"><span style="color:#C3E88D;">            Oxygen, Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue,</span></span>
<span class="line"><span style="color:#C3E88D;">            sans-serif;</span></span>
<span class="line"><span style="color:#C3E88D;">        }</span></span>
<span class="line"><span style="color:#C3E88D;">        * {</span></span>
<span class="line"><span style="color:#C3E88D;">          box-sizing: border-box;</span></span>
<span class="line"><span style="color:#C3E88D;">        }</span></span>
<span class="line"><span style="color:#89DDFF;">`</span><span style="color:#89DDFF;">}&lt;/</span><span style="color:#F07178;">style</span><span style="color:#89DDFF;">&gt;</span></span>
<span class="line"></span></code></pre></div><h2 id="设置路由" tabindex="-1">设置路由 <a class="header-anchor" href="#设置路由" aria-hidden="true">#</a></h2><p>前文已经说过了，我们可以通过 pages 文件夹的目录来配置我们的路由，pages/test/new.js 文件你需要使用 localhost:3000/test/new 进行访问，我们可以在页面中使用 link 组件实现页面的跳转，这个组件将直接将路由变成 href 指向的位置</p><div class="language-html"><button class="copy"></button><span class="lang">html</span><pre><code><span class="line"><span style="color:#A6ACCD;">import Link from &#39;next/link&#39;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#89DDFF;">&lt;</span><span style="color:#F07178;">div</span><span style="color:#89DDFF;">&gt;&lt;</span><span style="color:#F07178;">Link</span><span style="color:#89DDFF;"> </span><span style="color:#C792EA;">href</span><span style="color:#89DDFF;">=</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">/test/new</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">&gt;</span><span style="color:#A6ACCD;">去测试页面</span><span style="color:#89DDFF;">&lt;/</span><span style="color:#F07178;">Link</span><span style="color:#89DDFF;">&gt;&lt;/</span><span style="color:#F07178;">div</span><span style="color:#89DDFF;">&gt;</span></span>
<span class="line"></span></code></pre></div><p>你也可以使用 Router 组件进行路由的跳转，它在 js 里实现</p><div class="language-html"><button class="copy"></button><span class="lang">html</span><pre><code><span class="line"><span style="color:#A6ACCD;">import { useRouter } from &#39;next/router&#39;</span></span>
<span class="line"><span style="color:#A6ACCD;">const router = useRouter()</span></span>
<span class="line"></span>
<span class="line"><span style="color:#89DDFF;">&lt;</span><span style="color:#F07178;">button</span><span style="color:#89DDFF;"> </span><span style="color:#C792EA;">onClick</span><span style="color:#89DDFF;">=</span><span style="color:#C3E88D;">{()</span><span style="color:#89DDFF;">=&gt;</span><span style="color:#A6ACCD;">{router.push(&#39;/test/new&#39;)}}&gt;去测试页面</span><span style="color:#89DDFF;">&lt;/</span><span style="color:#F07178;">button</span><span style="color:#89DDFF;">&gt;</span></span>
<span class="line"></span></code></pre></div><p>你可以在跳转的路由中设置路径参数，目前只支持 /test/new?id=1 这样形式的路径参数，你可以使用 router 来获取你需要的路径参数</p><div class="language-javascript"><button class="copy"></button><span class="lang">javascript</span><pre><code><span class="line"><span style="color:#676E95;">//传递参数</span></span>
<span class="line"><span style="color:#89DDFF;">&lt;</span><span style="color:#FFCB6B;">Link</span><span style="color:#89DDFF;"> </span><span style="color:#C792EA;">href</span><span style="color:#89DDFF;">={{</span><span style="color:#F07178;">pathname</span><span style="color:#89DDFF;">:</span><span style="color:#89DDFF;">&#39;</span><span style="color:#C3E88D;">/test/new</span><span style="color:#89DDFF;">&#39;</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;">query</span><span style="color:#89DDFF;">:{</span><span style="color:#F07178;">id</span><span style="color:#89DDFF;">:</span><span style="color:#F78C6C;">1</span><span style="color:#89DDFF;">}}&gt;&lt;</span><span style="color:#F07178;">a</span><span style="color:#89DDFF;">&gt;</span><span style="color:#A6ACCD;">博客详情</span><span style="color:#89DDFF;">&lt;/</span><span style="color:#F07178;">a</span><span style="color:#89DDFF;">&gt;&lt;/</span><span style="color:#A6ACCD;">Link</span><span style="color:#89DDFF;">&gt;</span></span>
<span class="line"><span style="color:#A6ACCD;">router</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">push</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">     </span><span style="color:#F07178;">pathname</span><span style="color:#89DDFF;">:</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">/test/new</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#A6ACCD;">     </span><span style="color:#F07178;">query</span><span style="color:#89DDFF;">:{</span></span>
<span class="line"><span style="color:#A6ACCD;">         </span><span style="color:#F07178;">id</span><span style="color:#89DDFF;">:</span><span style="color:#F78C6C;">1</span></span>
<span class="line"><span style="color:#A6ACCD;">     </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#89DDFF;">}</span><span style="color:#A6ACCD;">)</span></span>
<span class="line"></span>
<span class="line"><span style="color:#676E95;">//获取参数</span></span>
<span class="line"><span style="color:#A6ACCD;">router</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">query</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">id</span></span>
<span class="line"></span></code></pre></div><p>当然除了使用路径参数的方式以外，next 也支持我们使用动态路由，如果你需要某一级的路由是动态的，你需要用 [ ] 把它包裹起来，比如，page/[id]/[pid].js，其中的 [id] 和 [pid] 两级都是动态路由，你可以使用任何形式匹配它，比如 localhost:3000/123/000 这样的形式，动态路由的参数将被处理为路径参数一起绑定在query 上，我们还是可以用 router 模块来获取它：</p><div class="language-javascript"><button class="copy"></button><span class="lang">javascript</span><pre><code><span class="line"><span style="color:#89DDFF;">import</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">useRouter</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">}</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">from</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&#39;</span><span style="color:#C3E88D;">next/router</span><span style="color:#89DDFF;">&#39;</span></span>
<span class="line"></span>
<span class="line"><span style="color:#C792EA;">const</span><span style="color:#A6ACCD;"> Post </span><span style="color:#89DDFF;">=</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">()</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">=&gt;</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#C792EA;">const</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">router</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#82AAFF;">useRouter</span><span style="color:#F07178;">()</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#C792EA;">const</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">{</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">pid</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">}</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">router</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">query</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#C792EA;">const</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">{</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">id</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">}</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">router</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">query</span></span>
<span class="line"></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;">return</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">&lt;</span><span style="color:#F07178;">p</span><span style="color:#89DDFF;">&gt;{</span><span style="color:#A6ACCD;">id</span><span style="color:#89DDFF;">}</span><span style="color:#A6ACCD;">: </span><span style="color:#89DDFF;">{</span><span style="color:#A6ACCD;">pid</span><span style="color:#89DDFF;">}&lt;/</span><span style="color:#F07178;">p</span><span style="color:#89DDFF;">&gt;</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#89DDFF;">export</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">default</span><span style="color:#A6ACCD;"> Post</span></span>
<span class="line"><span style="color:#676E95;">//显示123: 000</span></span>
<span class="line"></span></code></pre></div><p>你可以使用 [...slug] 这样的命名法，那么这个参数将会捕获所有满足的路由，即使它有下一级路由，举个简单的例子：当你使用 pages/test/[...slug].js 来命名时</p><div class="language-javascript"><button class="copy"></button><span class="lang">javascript</span><pre><code><span class="line"><span style="color:#676E95;">// pages/test/a</span></span>
<span class="line"><span style="color:#89DDFF;">{</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">slug</span><span style="color:#89DDFF;">&quot;</span><span style="color:#F07178;">: [</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">a</span><span style="color:#89DDFF;">&quot;</span><span style="color:#F07178;">] </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#676E95;">// pages/test/a/b</span></span>
<span class="line"><span style="color:#89DDFF;">{</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">slug</span><span style="color:#89DDFF;">&quot;</span><span style="color:#F07178;">: [</span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">a</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">b</span><span style="color:#89DDFF;">&quot;</span><span style="color:#F07178;">] </span><span style="color:#89DDFF;">}</span></span>
<span class="line"></span></code></pre></div><p>此外我们的路由模块还可以绑定处理不同阶段的事件，这里简单介绍，更多信息可以查阅官网文档：</p><p><a href="https://www.nextjs.cn/docs/routing/introduction" target="_blank" rel="noreferrer">https://www.nextjs.cn/docs/routing/introduction</a></p><div class="language-javascript"><button class="copy"></button><span class="lang">javascript</span><pre><code><span class="line"><span style="color:#676E95;">//路由发生变化时</span></span>
<span class="line"><span style="color:#A6ACCD;">Router</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">events</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">on</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">&#39;</span><span style="color:#C3E88D;">routeChangeStart</span><span style="color:#89DDFF;">&#39;</span><span style="color:#89DDFF;">,(...</span><span style="color:#A6ACCD;">args</span><span style="color:#89DDFF;">)</span><span style="color:#C792EA;">=&gt;</span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#89DDFF;">}</span><span style="color:#A6ACCD;">)</span></span>
<span class="line"></span>
<span class="line"><span style="color:#676E95;">//路由结束变化时</span></span>
<span class="line"><span style="color:#A6ACCD;">Router</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">events</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">on</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">&#39;</span><span style="color:#C3E88D;">routeChangeComplete</span><span style="color:#89DDFF;">&#39;</span><span style="color:#89DDFF;">,(...</span><span style="color:#A6ACCD;">args</span><span style="color:#89DDFF;">)</span><span style="color:#C792EA;">=&gt;</span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#89DDFF;">}</span><span style="color:#A6ACCD;">)</span></span>
<span class="line"></span>
<span class="line"><span style="color:#676E95;">//浏览器 history触发前</span></span>
<span class="line"><span style="color:#A6ACCD;">Router</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">events</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">on</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">&#39;</span><span style="color:#C3E88D;">beforeHistoryChange</span><span style="color:#89DDFF;">&#39;</span><span style="color:#89DDFF;">,(...</span><span style="color:#A6ACCD;">args</span><span style="color:#89DDFF;">)</span><span style="color:#C792EA;">=&gt;</span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#89DDFF;">}</span><span style="color:#A6ACCD;">)</span></span>
<span class="line"></span>
<span class="line"><span style="color:#676E95;">//路由跳转发生错误时</span></span>
<span class="line"><span style="color:#A6ACCD;">Router</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">events</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">on</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">&#39;</span><span style="color:#C3E88D;">routeChangeError</span><span style="color:#89DDFF;">&#39;</span><span style="color:#89DDFF;">,(...</span><span style="color:#A6ACCD;">args</span><span style="color:#89DDFF;">)</span><span style="color:#C792EA;">=&gt;</span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#89DDFF;">}</span><span style="color:#A6ACCD;">)</span></span>
<span class="line"></span></code></pre></div><h2 id="页面数据获取" tabindex="-1">页面数据获取 <a class="header-anchor" href="#页面数据获取" aria-hidden="true">#</a></h2><p>在静态生成预渲染阶段，我们的页面组件需要使用到外部数据接收参数，通常使用到Next.js提供的函数，有三种常用的函数：</p><ol><li>getStaticProps（静态生成）：在构建时获取数据。</li><li>getStaticPaths（静态生成）：指定动态路由以根据数据预渲染页面。</li><li>getServerSideProps（服务器端渲染）：获取每个请求的数据。</li></ol><p><strong>两种预渲染的区别请查看 Next 预渲染这节的内容</strong></p><ul><li>getStaticProps</li></ul><p>如果从页面export 名为 getStaticProps 的异步函数，Next.js 将在构建时使用 getStaticProps 返回的props预渲染此页面。你可以在 getStaticProps 逻辑里获取需要的数据，再将数据传递给页面，因为你必须先获取数据再渲染界面，所以你的方法需要用 async 包裹：</p><div class="language-javascript"><button class="copy"></button><span class="lang">javascript</span><pre><code><span class="line"><span style="color:#676E95;">// 根据传入的数据渲染界面</span></span>
<span class="line"><span style="color:#C792EA;">function</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">Blog</span><span style="color:#89DDFF;">({</span><span style="color:#A6ACCD;"> </span><span style="color:#A6ACCD;">posts</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">})</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;">return</span><span style="color:#F07178;"> (</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#89DDFF;">&lt;</span><span style="color:#F07178;">ul</span><span style="color:#89DDFF;">&gt;</span></span>
<span class="line"><span style="color:#A6ACCD;">      </span><span style="color:#89DDFF;">{</span><span style="color:#A6ACCD;">posts</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">map</span><span style="color:#A6ACCD;">(</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">post</span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">=&gt;</span><span style="color:#A6ACCD;"> (</span></span>
<span class="line"><span style="color:#A6ACCD;">        </span><span style="color:#89DDFF;">&lt;</span><span style="color:#F07178;">li</span><span style="color:#89DDFF;">&gt;{</span><span style="color:#A6ACCD;">post</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">title</span><span style="color:#89DDFF;">}&lt;/</span><span style="color:#F07178;">li</span><span style="color:#89DDFF;">&gt;</span></span>
<span class="line"><span style="color:#A6ACCD;">      ))</span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">&lt;/</span><span style="color:#F07178;">ul</span><span style="color:#89DDFF;">&gt;</span></span>
<span class="line"><span style="color:#F07178;">  )</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#676E95;">// 此函数在构建时被调用</span></span>
<span class="line"><span style="color:#89DDFF;">export</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">async</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">function</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">getStaticProps</span><span style="color:#89DDFF;">()</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#89DDFF;">  </span><span style="color:#676E95;">// 假设这是一个api 可以获取一些 json数据</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#C792EA;">const</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">res</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">await</span><span style="color:#F07178;"> </span><span style="color:#82AAFF;">fetch</span><span style="color:#F07178;">(</span><span style="color:#89DDFF;">&#39;</span><span style="color:#C3E88D;">https://...</span><span style="color:#89DDFF;">&#39;</span><span style="color:#F07178;">)</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#C792EA;">const</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">posts</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">await</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">res</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">json</span><span style="color:#F07178;">()</span></span>
<span class="line"></span>
<span class="line"><span style="color:#89DDFF;">  </span><span style="color:#676E95;">// 通过返回 { props: { posts } } 对象，Blog 组件</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;">return</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">    props</span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">      </span><span style="color:#A6ACCD;">posts</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#F07178;">    </span><span style="color:#89DDFF;">},</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#89DDFF;">export</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">default</span><span style="color:#A6ACCD;"> Blog</span></span>
<span class="line"></span></code></pre></div><p>如果你希望在动态路由中使用上述的方案，那么你需要使用 getStaticPaths ，因为构建动态路由所对应的内容时可能需要从外部获取数据，但是 next 并不知道那些动态路由页面需要渲染，getStaticPaths 函数在构建时被调用，并允许你指定要预渲染的路径。</p><div class="language-javascript"><button class="copy"></button><span class="lang">javascript</span><pre><code><span class="line"><span style="color:#676E95;">// 此函数在构建时被调用</span></span>
<span class="line"><span style="color:#89DDFF;">export</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">async</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">function</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">getStaticPaths</span><span style="color:#89DDFF;">()</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#89DDFF;">  </span><span style="color:#676E95;">// 假设这是一个api ，可以获取博文列表</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#C792EA;">const</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">res</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">await</span><span style="color:#F07178;"> </span><span style="color:#82AAFF;">fetch</span><span style="color:#F07178;">(</span><span style="color:#89DDFF;">&#39;</span><span style="color:#C3E88D;">https://...</span><span style="color:#89DDFF;">&#39;</span><span style="color:#F07178;">)</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#C792EA;">const</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">posts</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">await</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">res</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">json</span><span style="color:#F07178;">()</span></span>
<span class="line"></span>
<span class="line"><span style="color:#89DDFF;">  </span><span style="color:#676E95;">// 据博文列表生成所有需要预渲染的路径</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#C792EA;">const</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">paths</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">posts</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">map</span><span style="color:#F07178;">(</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">post</span><span style="color:#89DDFF;">)</span><span style="color:#F07178;"> </span><span style="color:#C792EA;">=&gt;</span><span style="color:#F07178;"> (</span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">    params</span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">{</span><span style="color:#F07178;"> id</span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">post</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">id</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">},</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;">}</span><span style="color:#F07178;">))</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;">return</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">{</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">paths</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> fallback</span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> </span><span style="color:#FF9CAC;">false</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#676E95;">// 在构建时也会被调用</span></span>
<span class="line"><span style="color:#89DDFF;">export</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">async</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">function</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">getStaticProps</span><span style="color:#89DDFF;">({</span><span style="color:#A6ACCD;"> </span><span style="color:#A6ACCD;">params</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">})</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#89DDFF;">  </span><span style="color:#676E95;">// params 包含此片博文的 `id` 信息。假设我们的 api 根据id返回数据，就可以这样传入了</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#C792EA;">const</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">res</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">await</span><span style="color:#F07178;"> </span><span style="color:#82AAFF;">fetch</span><span style="color:#F07178;">(</span><span style="color:#89DDFF;">`</span><span style="color:#C3E88D;">https://.....?=</span><span style="color:#89DDFF;">${</span><span style="color:#A6ACCD;">params</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">id</span><span style="color:#89DDFF;">}`</span><span style="color:#F07178;">)</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#C792EA;">const</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">post</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">await</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">res</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">json</span><span style="color:#F07178;">()</span></span>
<span class="line"></span>
<span class="line"><span style="color:#89DDFF;">  </span><span style="color:#676E95;">// 通过 props 参数向页面传递博文的数据</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;">return</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">{</span><span style="color:#F07178;"> props</span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">{</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">post</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">}</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span></code></pre></div><p>对于需要服务端渲染的界面，你可以编写 <code>getServerSideProps</code> 获取该数据并将其传递给 <code>Page</code> ，其用法和getStaticProps 如出一辙：</p><div class="language-javascript"><button class="copy"></button><span class="lang">javascript</span><pre><code><span class="line"><span style="color:#C792EA;">function</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">Page</span><span style="color:#89DDFF;">({</span><span style="color:#A6ACCD;"> </span><span style="color:#A6ACCD;">data</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">})</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#89DDFF;">  </span><span style="color:#676E95;">// Render data...</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#89DDFF;">export</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">async</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">function</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">getServerSideProps</span><span style="color:#89DDFF;">()</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#89DDFF;">  </span><span style="color:#676E95;">// 假设这是一个api 可以获取一些 json数据</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#C792EA;">const</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">res</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">await</span><span style="color:#F07178;"> </span><span style="color:#82AAFF;">fetch</span><span style="color:#F07178;">(</span><span style="color:#89DDFF;">`</span><span style="color:#C3E88D;">https://...</span><span style="color:#89DDFF;">`</span><span style="color:#F07178;">)</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#C792EA;">const</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">data</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">await</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">res</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">json</span><span style="color:#F07178;">()</span></span>
<span class="line"></span>
<span class="line"><span style="color:#89DDFF;">  </span><span style="color:#676E95;">// 传递数据</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#89DDFF;">return</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">{</span><span style="color:#F07178;"> props</span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">{</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">data</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">}</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span>
<span class="line"><span style="color:#89DDFF;">export</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">default</span><span style="color:#A6ACCD;"> Page</span></span>
<span class="line"></span></code></pre></div><h2 id="api路由" tabindex="-1">API路由 <a class="header-anchor" href="#api路由" aria-hidden="true">#</a></h2><p>API 路由为使用 Next.js 构建自己的 API 提供了一种简单的解决方案。也就是说，你可以将 next 应用作为提供html 页面的前端，也作为操作数据库进行数据查询修改的后端。</p><p>在 pages/api 目录下的任何文件都将作为 API 端点映射到 /api/ ，例如请求接口 <code>/api/user</code> next就会去pages/api文件夹下找到 <code>user.js / ts</code> 文件。</p><p>在接口文件中，我们 export default 一个方法来接收数据，然后操作后返回数据，方法提供两个实例res 和 req，用法和之前介绍的 node 的框架是基本一致的，详细的使用可以查看：</p><ul><li><code>req</code>: 一个 <a href="https://nodejs.org/api/http.html#http_class_http_incomingmessage" target="_blank" rel="noreferrer">http.IncomingMessage</a> 实例，以及一些 <a href="https://www.nextjs.cn/docs/api-routes/api-middlewares" target="_blank" rel="noreferrer">预先构建的中间件</a></li><li><code>res</code>: 一个 <a href="https://nodejs.org/api/http.html#http_class_http_serverresponse" target="_blank" rel="noreferrer">http.ServerResponse</a> 实例，以及一些 <a href="https://www.nextjs.cn/docs/api-routes/response-helpers" target="_blank" rel="noreferrer">辅助函数</a></li></ul><div class="language-javascript"><button class="copy"></button><span class="lang">javascript</span><pre><code><span class="line"><span style="color:#89DDFF;">export</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">default</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">req</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#A6ACCD;">res</span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">=&gt;</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#A6ACCD;">res</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">statusCode</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#F78C6C;">200</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#A6ACCD;">res</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">setHeader</span><span style="color:#F07178;">(</span><span style="color:#89DDFF;">&#39;</span><span style="color:#C3E88D;">Content-Type</span><span style="color:#89DDFF;">&#39;</span><span style="color:#89DDFF;">,</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">&#39;</span><span style="color:#C3E88D;">application/json</span><span style="color:#89DDFF;">&#39;</span><span style="color:#F07178;">)</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#A6ACCD;">res</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">end</span><span style="color:#F07178;">(</span><span style="color:#A6ACCD;">JSON</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">stringify</span><span style="color:#F07178;">(</span><span style="color:#89DDFF;">{</span><span style="color:#F07178;"> name</span><span style="color:#89DDFF;">:</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">&#39;</span><span style="color:#C3E88D;">John Doe</span><span style="color:#89DDFF;">&#39;</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">}</span><span style="color:#F07178;">)) </span><span style="color:#676E95;">// 接口会返回这条数据</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span></code></pre></div><p>同样的 api 路由也支持动态路由，使用方法和页面路由是一样的，不过我们使用 req 来接收参数</p><div class="language-javascript"><button class="copy"></button><span class="lang">javascript</span><pre><code><span class="line"><span style="color:#89DDFF;">export</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">default</span><span style="color:#A6ACCD;"> </span><span style="color:#C792EA;">function</span><span style="color:#A6ACCD;"> </span><span style="color:#82AAFF;">handler</span><span style="color:#89DDFF;">(</span><span style="color:#A6ACCD;">req</span><span style="color:#89DDFF;">,</span><span style="color:#A6ACCD;"> </span><span style="color:#A6ACCD;">res</span><span style="color:#89DDFF;">)</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#C792EA;">const</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">{</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">pid</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">}</span><span style="color:#F07178;"> </span><span style="color:#89DDFF;">=</span><span style="color:#F07178;"> </span><span style="color:#A6ACCD;">req</span><span style="color:#89DDFF;">.</span><span style="color:#A6ACCD;">query</span></span>
<span class="line"><span style="color:#F07178;">  </span><span style="color:#A6ACCD;">res</span><span style="color:#89DDFF;">.</span><span style="color:#82AAFF;">end</span><span style="color:#F07178;">(</span><span style="color:#89DDFF;">`</span><span style="color:#C3E88D;">Post: </span><span style="color:#89DDFF;">${</span><span style="color:#A6ACCD;">pid</span><span style="color:#89DDFF;">}`</span><span style="color:#F07178;">)</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span></code></pre></div><p>和 node 类似 API 路由也提供了内置的中间件，有哪些常用的中间键具体可以查看官方文档</p><p><a href="https://www.nextjs.cn/docs/api-routes/api-middlewares" target="_blank" rel="noreferrer">https://www.nextjs.cn/docs/api-routes/api-middlewares</a></p><h2 id="部署" tabindex="-1">部署 <a class="header-anchor" href="#部署" aria-hidden="true">#</a></h2><p>Next.js 可以部署到任何安装 Node.js 服务器。可以看到 package.json 中：</p><div class="language-json"><button class="copy"></button><span class="lang">json</span><pre><code><span class="line"><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">  </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C792EA;">scripts</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">{</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">&quot;</span><span style="color:#FFCB6B;">dev</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">next</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">&quot;</span><span style="color:#FFCB6B;">build</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">next build</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">,</span></span>
<span class="line"><span style="color:#A6ACCD;">    </span><span style="color:#89DDFF;">&quot;</span><span style="color:#FFCB6B;">start</span><span style="color:#89DDFF;">&quot;</span><span style="color:#89DDFF;">:</span><span style="color:#A6ACCD;"> </span><span style="color:#89DDFF;">&quot;</span><span style="color:#C3E88D;">next start</span><span style="color:#89DDFF;">&quot;</span></span>
<span class="line"><span style="color:#A6ACCD;">  </span><span style="color:#89DDFF;">}</span></span>
<span class="line"><span style="color:#89DDFF;">}</span></span>
<span class="line"></span></code></pre></div><p>执行一次 <code>npm run build</code> 脚本，可以文件夹中构建生产应用程序 <code>.next</code>；</p><p>运行 <code>npm run start</code> 就能启动一个支持混合页面的 Node.js 服务器，为静态生成的和服务器端呈现的页面以及 API 路由提供服务。</p><h2 id="项目" tabindex="-1">项目 <a class="header-anchor" href="#项目" aria-hidden="true">#</a></h2><p>这里提供一些字节的官方的教学提供的项目：</p><ul><li>SSR 实现： <a href="https://link.juejin.cn/?target=https%3A%2F%2Fgithub.com%2Fczm1290433700%2Fssr-server" target="_blank" rel="noreferrer">github.com/czm12904337…</a></li><li>CMS 仓库地址：<a href="https://link.juejin.cn/?target=https%3A%2F%2Fgithub.com%2Fczm1290433700%2Fnextjs-cms" target="_blank" rel="noreferrer">github.com/czm12904337…</a></li><li>Demo 仓库地址： <a href="https://link.juejin.cn/?target=https%3A%2F%2Fgithub.com%2Fczm1290433700%2Fnextjs-demo" target="_blank" rel="noreferrer">github.com/czm12904337…</a></li></ul><p>更多的原理性的内容可以查看：<a href="https://juejin.cn/book/7137945369635192836" target="_blank" rel="noreferrer">https://juejin.cn/book/7137945369635192836</a></p></div></div></main><!--[--><!--]--><footer class="VPDocFooter" data-v-37ebe389 data-v-a54a85bd><!----><div class="prev-next" data-v-a54a85bd><div class="pager" data-v-a54a85bd><a class="pager-link prev" href="/articles/basic-bitdance/class07-node.html" data-v-a54a85bd><span class="desc" data-v-a54a85bd>Previous page</span><span class="title" data-v-a54a85bd>class07-node</span></a></div><div class="has-prev pager" data-v-a54a85bd><a class="pager-link next" href="/articles/basic-bitdance/class08.5-%E5%BC%80%E5%8F%91%E6%8A%80%E5%B7%A7.html" data-v-a54a85bd><span class="desc" data-v-a54a85bd>Next page</span><span class="title" data-v-a54a85bd>class08.5-开发技巧</span></a></div></div></footer><!--[--><!--]--></div></div></div></div></div><!----><!--[--><!--]--></div></div>
    <script>__VP_HASH_MAP__ = JSON.parse("{\"articles_basic-bitdance_class01-html.md\":\"ff4ff513\",\"articles_basic-bitdance_class02-css.md\":\"a702a9f8\",\"articles_basic-bitdance_class03-js.md\":\"0cf4e640\",\"articles_basic-bitdance_class04-typescript.md\":\"6eb8a62e\",\"articles_basic-bitdance_class05-http.md\":\"cb129388\",\"articles_basic-bitdance_class06-react.md\":\"a4c71f1a\",\"articles_basic-bitdance_class07-node.md\":\"7925a6b7\",\"articles_basic-bitdance_class08-next.js.md\":\"893eef63\",\"articles_basic-bitdance_class08.5-开发技巧.md\":\"e6d7e150\",\"articles_basic-bitdance_class09-跨端技术.md\":\"25156c46\",\"articles_basic-bitdance_class10-调试.md\":\"f07f60c2\",\"articles_basic-bitdance_class11-安全.md\":\"3c992463\",\"articles_basic-bitdance_class12-监控sdk.md\":\"35ef00f1\",\"articles_basic-bitdance_class13-webpack.md\":\"70e5acc7\",\"articles_basic-bitdance_class14-vite.md\":\"9cfa31e3\",\"articles_basic-bitdance_class15-可视化.md\":\"4c9a2433\",\"articles_basic_index.md\":\"5c1f50b5\",\"articles_electron_index.md\":\"acb5a448\",\"articles_electron_测试.md\":\"5404a20a\",\"articles_mini_index.md\":\"9af79c7b\",\"articles_other_vitepress_01.vitepress的搭建.md\":\"b8deb5b2\",\"articles_other_vitepress_02.vitepress的部署.md\":\"cf416a09\",\"articles_other_vitepress_03.vitepress自动生成目录.md\":\"0dd6d021\",\"articles_other_vitepress_04.vitepress引入vue组件.md\":\"46052034\",\"articles_react_index.md\":\"ec69e04d\",\"articles_react_source code_01.react的架构.md\":\"f4181c9b\",\"articles_rust_01.基础入门.md\":\"af35ebe7\",\"articles_rust_02.基础语法.md\":\"eba033ca\",\"articles_rust_03.指针与内存分配.md\":\"b6d4df62\",\"articles_rust_04.程序结构和异常处理.md\":\"07567152\",\"articles_rust_05.数据结构与泛型.md\":\"6d5c530d\",\"articles_rust_06.trait与生命周期.md\":\"5e57b7aa\",\"articles_rust_07.编写测试.md\":\"bd7d6015\",\"articles_rust_08.构建命令行程序.md\":\"a295a848\",\"articles_rust_09.闭包与迭代器.md\":\"cf79a80f\",\"articles_rust_10.发布项目.md\":\"9e4f6be1\",\"articles_rust_11.智能指针.md\":\"48ecbccd\",\"articles_rust_12.并发.md\":\"62f8f67e\",\"articles_rust_13.面向对象.md\":\"a8519b1a\",\"articles_rust_14.不安全rust.md\":\"a079df80\",\"articles_rust_15.高级特性.md\":\"2b09c61c\",\"articles_rust_16.手写web服务器和线程池.md\":\"97f59e40\",\"articles_rust_17.rust异步编程.md\":\"e26606a3\",\"articles_rustweb_01.简单 server.md\":\"6c2ab750\",\"articles_rustweb_02.actix.md\":\"048a9c59\",\"articles_rustweb_03.连接数据库.md\":\"5ccb794e\",\"articles_rustweb_04.错误处理.md\":\"bd3759f6\",\"articles_rustweb_05.完整项目重构.md\":\"d160a226\",\"articles_rustweb_06.服务器端web应用.md\":\"cdc4f4ca\",\"articles_rustweb_07.webassembly.md\":\"0f1bc773\",\"articles_rustweb_08.发布.md\":\"d4792485\",\"articles_vue_index.md\":\"5ded6ffa\",\"articles_vue组件库_vue3组件库项目学习笔记（1）：基础搭建.md\":\"23c5186c\",\"articles_vue组件库_vue3组件库项目学习笔记（2）：开发一个组件.md\":\"fdd9e315\",\"articles_vue组件库_vue3组件库项目学习笔记（3）：测试你的组件.md\":\"7a02b7b2\",\"articles_vue组件库_vue3组件库项目学习笔记（4）：发布你的组件.md\":\"e0b3816e\",\"articles_vue组件库_vue3组件库项目学习笔记（5）：配置编码规范.md\":\"291e9a8e\",\"articles_vue组件库_vue3组件库项目学习笔记（6）：发布组件文档.md\":\"3fa49d31\",\"articles_vue组件库_vue3组件库项目学习笔记（7）：正式开发问题拾遗.md\":\"85204ad9\",\"articles_vue组件库_vue3组件库项目学习笔记（8）：git协作.md\":\"ab61313a\",\"articles_web3d_index.md\":\"a52fc82e\",\"index.md\":\"de494fc0\",\"intent_index.md\":\"82efde64\",\"leetcode_leet_code题解_47. 全排列 ii.md\":\"c8680b3d\",\"leetcode_leet_code题解_49. 字母异位词分组.md\":\"e37b3116\",\"leetcode_leet_code题解_55. 跳跃游戏.md\":\"29658916\",\"leetcode_leet_code题解_56. 合并区间.md\":\"8f16bd71\",\"public_draco_readme.md\":\"5da4c955\"}")</script>
    <script type="module" async src="/assets/app.75d9ecf2.js"></script>
    
  </body>
</html>